import { Injectable } from '@nestjs/common';
import { CrudService } from '../../common/crud/crud.service';
import { PrismaService } from 'nestjs-prisma';
import { CreateStyleDto } from './dto/create-style.dto';
import { UpdateStyleDto } from './dto/update-style.dto';
import { CreateStyleProcessDto } from './dto/create-style-process.dto';
import { CreateProcessDto } from '../process/dto/create-process.dto';

@Injectable()
export class StyleService extends CrudService {
  constructor(readonly prisma: PrismaService) {
    super(prisma, 'style');
  }

  async create(form: CreateStyleDto) {
    const sizes = form.sizes;
    delete form.sizes;
    const style = await this.prisma.style.create({
      data: {
        modelId: form.modelId,
        groupId: form.groupId,
        description: form.description,
        sizes: {
          createMany: {
            data: sizes.map((size) => {
              return {
                sizeId: size.sizeId,
                amount: size.amount,
              };
            }),
          },
        },
      },
    });
    if (form.copyId) {
      const process = await this.prisma.process.findMany({
        where: {
          styleId: form.copyId,
        },
        include: {
          prices: true,
        },
      });

      const processForm: CreateStyleProcessDto = {
        process: [],
      };
      process.forEach((pro, index) => {
        processForm.process.push({
          index: index + 1,
          name: pro.name,
          prices: pro.prices.map((p) => {
            return {
              sizeId: p.sizeId,
              price: p.price,
            };
          }),
        });
      });

      await this.createProcess(style.id, processForm);
    }
    return style;
  }

  async createProcess(id: string, form: CreateStyleProcessDto) {
    const deletePrices = this.prisma.processPrice.deleteMany({
      where: {
        process: {
          styleId: id,
        },
      },
    });
    const deleteProcess = this.prisma.process.deleteMany({
      where: {
        styleId: id,
      },
    });

    const createTemplates = form.process.map((p) => {
      return this.prisma.processTemplate.upsert({
        where: {
          name: p.name,
        },
        update: {
          prices: {
            deleteMany: {},
            createMany: {
              data: p.prices.map((price) => {
                return {
                  price: price.price,
                  sizeId: price.sizeId,
                };
              }),
            },
          },
        },
        create: {
          name: p.name,
          prices: {
            createMany: {
              data: p.prices.map((price) => {
                return {
                  price: price.price,
                  sizeId: price.sizeId,
                };
              }),
            },
          },
        },
      });
    });

    const createMany = form.process.map((p) => {
      return this.prisma.process.create({
        data: {
          styleId: id,
          name: p.name,
          index: p.index,
          prices: {
            createMany: {
              data: p.prices.map((price) => {
                return {
                  price: price.price,
                  sizeId: price.sizeId,
                };
              }),
            },
          },
        },
      });
    });

    await this.prisma.$transaction([
      deletePrices,
      deleteProcess,
      ...createMany,
      ...createTemplates,
    ]);
    return 'ok';
  }

  update(id: string, form: UpdateStyleDto) {
    const sizes = form.sizes;
    delete form.sizes;
    return this.prisma.style.update({
      where: { id },
      data: {
        modelId: form.modelId,
        groupId: form.groupId,
        description: form.description,
        sizes: {
          deleteMany: {},
          createMany: {
            data: sizes.map((size) => {
              return {
                sizeId: size.sizeId,
                amount: size.amount,
              };
            }),
          },
        },
      },
    });
  }

  async remove(id: string) {
    const deleteStyleOnSizes = this.prisma.styleOnSize.deleteMany({
      where: {
        styleId: id,
      },
    });

    const del = this.prisma.style.delete({
      where: {
        id,
      },
    });

    await this.prisma.$transaction([deleteStyleOnSizes, del]);
    return 'ok';
  }

  findOne(id: string) {
    return this.prisma.style.findUnique({
      where: {
        id,
      },
      include: {
        sizes: {
          select: {
            sizeId: true,
            amount: true,
            size: true,
          },
        },
        model: {
          select: {
            code: true,
            id: true,
            name: true,
          },
        },
        group: {
          select: {
            id: true,
            name: true,
          },
        },
        process: {
          select: {
            id: true,
            index: true,
            name: true,
            prices: true,
          },
        },
      },
    });
  }
}
